package juc.mythread.communication;

/**
 * @ClassName volatileTest
 * @PackageName mythread.communication
 * @projectName myThreadvolatile的
 * @Description 
 * @Author games
 * @Date 2025/8/25 上午9:36
 * @Version 1.0
 */
public class Test2Volatile {

    /**
     * volatile 使用注意事项
     * 1. 适用场景限制
     * 适用情况：
     * volatile 适用于变量的读写操作具有原子性的情况（如基本类型变量）
     * 用于状态标志位，实现线程间通信
     * 双重检查锁定模式中的单例实例引用
     * 不适用情况：
     * 复合操作（如 i++、count += 10）不能保证原子性
     * 需要保证多个变量之间一致性的情况
     * 2. 内存语义理解
     * volatile 提供 happens-before 关系保证
     * 对 volatile 变量的写操作对后续读操作可见
     * 禁止指令重排序优化
     * 3. 性能考虑
     * volatile 变量的读写比普通变量开销大
     * 但比使用 synchronized 关键字轻量
     * 避免过度使用，只在必要时使用
     * // 错误示例：非原子操作
     * volatile int count = 0;
     * count++; // 这不是原子操作，仍需要同步
     *
     * // 正确示例：状态标志
     * volatile boolean flag = false;
     * // 线程A
     * flag = true;
     *
     * // 线程B
     * while(!flag) {
     *     // 等待flag变为true
     * }
     * 5. 与其他同步机制的区别
     * volatile 不能替代 synchronized
     * 不提供互斥访问，只保证可见性和有序性
     * 对于复合操作仍需要使用锁机制
     * 6. 使用建议
     * 优先考虑使用 java.util.concurrent 包中的高级同步工具
     * 只在确实需要可见性保证且操作是原子的情况下使用 volatile
     * 文档化说明使用 volatile 的原因和预期行为
     *
     *
     *
     * 原子操作和volatile的线程安全性
     * 什么是原子操作
     * 原子操作是指不可分割的操作，即该操作在执行过程中不会被其他线程中断。对于一个原子操作来说，要么完全执行完毕，要么完全没有执行，不存在中间状态。
     * 常见的原子操作包括：
     * 基本数据类型的读写操作（如int、boolean、double等）
     * 对引用类型变量的赋值操作
     * 使用java.util.concurrent.atomic包中的原子类操作
     *
     *
     * // 原子操作示例
     * int a = 5;        // 基本类型赋值是原子的
     * boolean flag = true; // boolean赋值是原子的
     *
     * // 非原子操作示例
     * i++;              // 包含读取、加1、写入三步操作
     * count += 10;      // 包含读取、计算、写入三步操作
     *
     * 这种情况下：
     * 虽然不会抛出异常
     * 但counter++操作不是原子的（包含读取、增加、写入三步）
     * 可能出现多个线程同时读取相同值，导致计数不准确
     * 总结
     * volatile变量的读写操作本身是线程安全的，不会抛出异常
     * 但对于复合操作（如自增、自减等），即使使用volatile也不是线程安全的
     * 如果需要对复合操作保证原子性，需要使用synchronized或java.util.concurrent.atomic包中的原子类
     */
    // 用volatile保证多线程间变量可见性
    private static volatile boolean stop = false;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("线程t1开始执行");
                int i = 0;
                while (!stop) {
                    i++;
                }
                System.out.println("跳出循环");
            }
        }, "t1");
        t1.start();

        Thread.sleep(1000);
        stop = true;
        System.out.println("主线程修改stop=true");
    }
}
